#!/bin/bash

# 设置颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 默认参数
INTERVAL=5      # 采样间隔（秒）
DURATION=60     # 监控时长（秒）
OUTPUT_FILE="cpu_performance_report_$(date +%Y%m%d_%H%M%S).txt"
STATIC_INFO_FILE="cpu_static_info_$(date +%Y%m%d_%H%M%S).txt"

# 帮助信息
show_help() {
    echo "用法: $0 [选项]"
    echo "选项:"
    echo "  -i, --interval <秒>   采样间隔（默认: 5秒）"
    echo "  -d, --duration <秒>   监控时长（默认: 60秒）"
    echo "  -o, --output <文件>   输出文件（默认: cpu_performance_report_时间戳.txt）"
    echo "  -s, --static <文件>   静态信息文件（默认: cpu_static_info_时间戳.txt）"
    echo "  -h, --help           显示此帮助信息"
    exit 0
}

# 解析命令行参数
while [[ $# -gt 0 ]]; do
    case $1 in
        -i|--interval)
            INTERVAL="$2"
            shift 2
            ;;
        -d|--duration)
            DURATION="$2"
            shift 2
            ;;
        -o|--output)
            OUTPUT_FILE="$2"
            shift 2
            ;;
        -s|--static)
            STATIC_INFO_FILE="$2"
            shift 2
            ;;
        -h|--help)
            show_help
            ;;
        *)
            echo "未知选项: $1"
            show_help
            ;;
    esac
done

# 收集CPU静态信息
collect_cpu_static_info() {
    echo "=== Linux CPU 静态信息 ===" > "$STATIC_INFO_FILE"
    echo "收集时间: $(date)" >> "$STATIC_INFO_FILE"
    echo "----------------------------------------" >> "$STATIC_INFO_FILE"
    
    # CPU基本信息
    echo -e "\n1. CPU基本信息:" >> "$STATIC_INFO_FILE"
    echo "----------------------------------------" >> "$STATIC_INFO_FILE"
    echo "CPU型号:" >> "$STATIC_INFO_FILE"
    cat /proc/cpuinfo | grep "model name" | head -n 1 | cut -d ':' -f 2 >> "$STATIC_INFO_FILE"
    echo "CPU核心数:" >> "$STATIC_INFO_FILE"
    nproc --all >> "$STATIC_INFO_FILE"
    echo "CPU线程数:" >> "$STATIC_INFO_FILE"
    grep -c ^processor /proc/cpuinfo >> "$STATIC_INFO_FILE"
    
    # CPU缓存信息
    echo -e "\n2. CPU缓存信息:" >> "$STATIC_INFO_FILE"
    echo "----------------------------------------" >> "$STATIC_INFO_FILE"
    echo "L1缓存:" >> "$STATIC_INFO_FILE"
    lscpu | grep "L1d cache" >> "$STATIC_INFO_FILE"
    echo "L2缓存:" >> "$STATIC_INFO_FILE"
    lscpu | grep "L2 cache" >> "$STATIC_INFO_FILE"
    echo "L3缓存:" >> "$STATIC_INFO_FILE"
    lscpu | grep "L3 cache" >> "$STATIC_INFO_FILE"
    
    # CPU频率信息
    echo -e "\n3. CPU频率信息:" >> "$STATIC_INFO_FILE"
    echo "----------------------------------------" >> "$STATIC_INFO_FILE"
    echo "当前CPU频率:" >> "$STATIC_INFO_FILE"
    cat /proc/cpuinfo | grep "cpu MHz" | head -n 1 | cut -d ':' -f 2 >> "$STATIC_INFO_FILE"
    echo "最大CPU频率:" >> "$STATIC_INFO_FILE"
    lscpu | grep "CPU max MHz" >> "$STATIC_INFO_FILE"
    echo "最小CPU频率:" >> "$STATIC_INFO_FILE"
    lscpu | grep "CPU min MHz" >> "$STATIC_INFO_FILE"
    
    # CPU架构信息
    echo -e "\n4. CPU架构信息:" >> "$STATIC_INFO_FILE"
    echo "----------------------------------------" >> "$STATIC_INFO_FILE"
    echo "架构:" >> "$STATIC_INFO_FILE"
    lscpu | grep "Architecture" >> "$STATIC_INFO_FILE"
    echo "运行模式:" >> "$STATIC_INFO_FILE"
    lscpu | grep "CPU op-modes" >> "$STATIC_INFO_FILE"
    echo "字节序:" >> "$STATIC_INFO_FILE"
    lscpu | grep "Byte Order" >> "$STATIC_INFO_FILE"
    
    # CPU特性
    echo -e "\n5. CPU特性:" >> "$STATIC_INFO_FILE"
    echo "----------------------------------------" >> "$STATIC_INFO_FILE"
    echo "CPU特性:" >> "$STATIC_INFO_FILE"
    cat /proc/cpuinfo | grep -A 1 "flags" | head -n 2 >> "$STATIC_INFO_FILE"
    
    # 虚拟化支持
    echo -e "\n6. 虚拟化支持:" >> "$STATIC_INFO_FILE"
    echo "----------------------------------------" >> "$STATIC_INFO_FILE"
    echo "虚拟化支持:" >> "$STATIC_INFO_FILE"
    lscpu | grep "Virtualization" >> "$STATIC_INFO_FILE"
    
    echo -e "\n静态信息收集完成，已保存到: $STATIC_INFO_FILE"
}

# 创建输出文件
echo "=== Linux CPU 性能监控报告 ===" > "$OUTPUT_FILE"
echo "开始时间: $(date)" >> "$OUTPUT_FILE"
echo "采样间隔: ${INTERVAL}秒" >> "$OUTPUT_FILE"
echo "监控时长: ${DURATION}秒" >> "$OUTPUT_FILE"
echo "----------------------------------------" >> "$OUTPUT_FILE"

# 收集CPU静态信息
echo -e "${BLUE}正在收集CPU静态信息...${NC}"
collect_cpu_static_info

# 初始化计数器
count=0
total_samples=$((DURATION / INTERVAL))

# 创建临时文件存储数据
temp_cpu_usage="/tmp/cpu_usage_$$.tmp"
temp_load="/tmp/load_$$.tmp"
temp_context="/tmp/context_$$.tmp"
temp_interrupts="/tmp/interrupts_$$.tmp"
temp_softirqs="/tmp/softirqs_$$.tmp"
temp_processes="/tmp/processes_$$.tmp"

# 创建临时文件
touch "$temp_cpu_usage" "$temp_load" "$temp_context" "$temp_interrupts" "$temp_softirqs" "$temp_processes"

# 清理函数
cleanup() {
    # 检查是否已经清理过
    if [ -n "$CLEANUP_DONE" ]; then
        return
    fi
    
    rm -f "$temp_cpu_usage" "$temp_load" "$temp_context" "$temp_interrupts" "$temp_softirqs" "$temp_processes"
    echo -e "\n${GREEN}监控已完成，报告已保存到: $OUTPUT_FILE${NC}"
    echo -e "${GREEN}静态信息已保存到: $STATIC_INFO_FILE${NC}"
    
    # 标记清理已完成
    CLEANUP_DONE=1
    
    # 只有在非正常退出时才退出
    if [ -n "$1" ]; then
        exit 1
    fi
}

# 设置清理陷阱
trap 'cleanup 1' EXIT INT TERM

echo -e "${BLUE}开始监控CPU性能...${NC}"
echo -e "采样间隔: ${INTERVAL}秒"
echo -e "监控时长: ${DURATION}秒"
echo -e "输出文件: $OUTPUT_FILE"
echo -e "按 Ctrl+C 可以提前结束监控\n"

# 主循环
while [ $count -lt $total_samples ]; do
    timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    # 收集详细CPU使用率
    cpu_info=$(top -bn1 | grep "%Cpu(s)")
    # 提取所有CPU指标，并去除百分号
    cpu_user=$(echo "$cpu_info" | awk '{print $2}' | tr -d '[:alpha:],')
    cpu_system=$(echo "$cpu_info" | awk '{print $4}' | tr -d '[:alpha:],')
    cpu_nice=$(echo "$cpu_info" | awk '{print $6}' | tr -d '[:alpha:],')
    cpu_idle=$(echo "$cpu_info" | awk '{print $8}' | tr -d '[:alpha:],')
    cpu_iowait=$(echo "$cpu_info" | awk '{print $10}' | tr -d '[:alpha:],')
    cpu_hardirq=$(echo "$cpu_info" | awk '{print $12}' | tr -d '[:alpha:],')
    cpu_softirq=$(echo "$cpu_info" | awk '{print $14}' | tr -d '[:alpha:],')
    cpu_steal=$(echo "$cpu_info" | awk '{print $16}' | tr -d '[:alpha:],')
    
    # 使用bc命令进行浮点数计算
    cpu_total=$(echo "scale=2; 100 - $cpu_idle" | bc)
    
    echo "$timestamp CPU_USAGE $cpu_total $cpu_user $cpu_system $cpu_nice $cpu_idle $cpu_iowait $cpu_hardirq $cpu_softirq $cpu_steal" >> "$temp_cpu_usage"
    
    # 收集平均负载
    load1=$(uptime | awk '{print $(NF-2)}' | tr -d ',')
    load5=$(uptime | awk '{print $(NF-1)}' | tr -d ',')
    load15=$(uptime | awk '{print $NF}' | tr -d ',')
    echo "$timestamp LOAD $load1 $load5 $load15" >> "$temp_load"
    
    # 收集上下文切换（区分主动和被动）
    total_context_switches=$(vmstat 1 2 | tail -n 1 | awk '{print $12}')
    
    # 获取主动和被动上下文切换数据
    voluntary_switches=0
    nonvoluntary_switches=0
    
    # 获取所有进程的主动和被动上下文切换总数
    for pid in $(ls /proc/ | grep -E '^[0-9]+$' 2>/dev/null); do
        if [ -f "/proc/$pid/status" ]; then
            vol=$(grep "voluntary_ctxt_switches" "/proc/$pid/status" 2>/dev/null | awk '{print $2}')
            nonvol=$(grep "nonvoluntary_ctxt_switches" "/proc/$pid/status" 2>/dev/null | awk '{print $2}')
            
            if [ -n "$vol" ] && [[ "$vol" =~ ^[0-9]+$ ]]; then
                voluntary_switches=$((voluntary_switches + vol))
            fi
            
            if [ -n "$nonvol" ] && [[ "$nonvol" =~ ^[0-9]+$ ]]; then
                nonvoluntary_switches=$((nonvoluntary_switches + nonvol))
            fi
        fi
    done
    
    echo "$timestamp CONTEXT $total_context_switches $voluntary_switches $nonvoluntary_switches" >> "$temp_context"
    
    # 收集中断次数（区分硬中断和软中断）
    # 硬中断总数
    hard_interrupts=$(grep -v "ERR:" /proc/interrupts | grep -v "MIS:" | grep -c ":")
    
    # 软中断总数及类型统计
    soft_interrupts=0
    echo "$timestamp SOFTIRQ_TYPES" > "$temp_softirqs.tmp"
    
    if [ -f "/proc/softirqs" ]; then
        # 软中断类型列表
        softirq_types=$(grep -o "^[A-Z_]*:" /proc/softirqs | tr -d ':')
        
        for type in $softirq_types; do
            # 获取该类型的所有CPU的值并求和
            type_count=0
            type_line=$(grep "$type:" /proc/softirqs)
            
            # 提取数值并求和
            for val in $(echo "$type_line" | grep -oE '[0-9]+'); do
                type_count=$((type_count + val))
            done
            
            echo "$type $type_count" >> "$temp_softirqs.tmp"
            soft_interrupts=$((soft_interrupts + type_count))
        done
    fi
    
    cat "$temp_softirqs.tmp" >> "$temp_softirqs"
    echo "$timestamp INTERRUPTS $hard_interrupts $soft_interrupts" >> "$temp_interrupts"
    
    # 收集CPU密集型进程
    echo "$timestamp PROCESSES" > "$temp_processes.tmp"
    ps -eo pid,pcpu,time,comm --sort=-pcpu | head -6 | tail -5 >> "$temp_processes.tmp"
    cat "$temp_processes.tmp" >> "$temp_processes"
    
    # 显示倒计时（每秒更新一次）
    remaining=$((DURATION - (count * INTERVAL)))
    for ((i=0; i<INTERVAL; i++)); do
        printf "\r${YELLOW}剩余时间: %d 秒${NC}" $((remaining - i))
        sleep 1
    done
    
    count=$((count + 1))
done

echo -e "\n\n${GREEN}正在生成报告...${NC}"

# 生成统计报告
echo -e "\n=== CPU使用率统计 ===" >> "$OUTPUT_FILE"
echo "时间戳                总使用率  用户空间  系统空间  优先级  空闲   IO等待  硬中断  软中断  窃取" >> "$OUTPUT_FILE"
echo "------------------------------------------------" >> "$OUTPUT_FILE"
while read -r line; do
    if [[ "$line" == *"CPU_USAGE"* ]]; then
        # 使用cut命令分割字段，更可靠
        timestamp=$(echo "$line" | cut -d' ' -f1,2)
        total=$(echo "$line" | cut -d' ' -f4)
        user=$(echo "$line" | cut -d' ' -f5)
        system=$(echo "$line" | cut -d' ' -f6)
        nice=$(echo "$line" | cut -d' ' -f7)
        idle=$(echo "$line" | cut -d' ' -f8)
        iowait=$(echo "$line" | cut -d' ' -f9)
        hardirq=$(echo "$line" | cut -d' ' -f10)
        softirq=$(echo "$line" | cut -d' ' -f11)
        steal=$(echo "$line" | cut -d' ' -f12)
        # 使用awk进行格式化输出
        awk -v ts="$timestamp" -v t="$total" -v u="$user" -v s="$system" -v n="$nice" -v i="$idle" -v w="$iowait" -v h="$hardirq" -v si="$softirq" -v st="$steal" \
            'BEGIN {printf "%-20s %9.2f%% %9.2f%% %9.2f%% %9.2f%% %9.2f%% %9.2f%% %9.2f%% %9.2f%% %9.2f%%\n", ts, t, u, s, n, i, w, h, si, st}' >> "$OUTPUT_FILE"
    fi
done < "$temp_cpu_usage"

echo -e "\n=== 系统平均负载统计 ===" >> "$OUTPUT_FILE"
echo "时间戳                1分钟    5分钟    15分钟" >> "$OUTPUT_FILE"
echo "------------------------------------------------" >> "$OUTPUT_FILE"
while read -r line; do
    if [[ "$line" == *"LOAD"* ]]; then
        timestamp=$(echo "$line" | cut -d' ' -f1,2)
        load1=$(echo "$line" | cut -d' ' -f4)
        load5=$(echo "$line" | cut -d' ' -f5)
        load15=$(echo "$line" | cut -d' ' -f6)
        awk -v ts="$timestamp" -v l1="$load1" -v l5="$load5" -v l15="$load15" \
            'BEGIN {printf "%-20s %8.2f %8.2f %8.2f\n", ts, l1, l5, l15}' >> "$OUTPUT_FILE"
    fi
done < "$temp_load"

echo -e "\n=== 上下文切换统计 ===" >> "$OUTPUT_FILE"
echo "时间戳                总切换    主动切换  被动切换" >> "$OUTPUT_FILE"
echo "------------------------------------------------" >> "$OUTPUT_FILE"
while read -r line; do
    if [[ "$line" == *"CONTEXT"* ]]; then
        timestamp=$(echo "$line" | cut -d' ' -f1,2)
        total=$(echo "$line" | cut -d' ' -f4)
        voluntary=$(echo "$line" | cut -d' ' -f5)
        nonvoluntary=$(echo "$line" | cut -d' ' -f6)
        awk -v ts="$timestamp" -v t="$total" -v v="$voluntary" -v nv="$nonvoluntary" \
            'BEGIN {printf "%-20s %8d %8d %8d\n", ts, t, v, nv}' >> "$OUTPUT_FILE"
    fi
done < "$temp_context"

echo -e "\n=== 中断统计 ===" >> "$OUTPUT_FILE"
echo "时间戳                硬中断    软中断" >> "$OUTPUT_FILE"
echo "------------------------------------------------" >> "$OUTPUT_FILE"
while read -r line; do
    if [[ "$line" == *"INTERRUPTS"* ]]; then
        timestamp=$(echo "$line" | cut -d' ' -f1,2)
        hard=$(echo "$line" | cut -d' ' -f4)
        soft=$(echo "$line" | cut -d' ' -f5)
        awk -v ts="$timestamp" -v h="$hard" -v s="$soft" \
            'BEGIN {printf "%-20s %8d %8d\n", ts, h, s}' >> "$OUTPUT_FILE"
    fi
done < "$temp_interrupts"

echo -e "\n=== 软中断类型统计 ===" >> "$OUTPUT_FILE"
echo "时间戳                类型    计数" >> "$OUTPUT_FILE"
echo "------------------------------------------------" >> "$OUTPUT_FILE"
last_timestamp=""
while read -r line; do
    if [[ "$line" == *"SOFTIRQ_TYPES"* ]]; then
        last_timestamp=$(echo "$line" | cut -d' ' -f1,2)
    elif [[ -n "$last_timestamp" && "$line" != *"SOFTIRQ_TYPES"* ]]; then
        type=$(echo "$line" | cut -d' ' -f1)
        count=$(echo "$line" | cut -d' ' -f2)
        awk -v ts="$last_timestamp" -v t="$type" -v c="$count" \
            'BEGIN {printf "%-20s %-10s %8d\n", ts, t, c}' >> "$OUTPUT_FILE"
    fi
done < "$temp_softirqs"

echo -e "\n=== CPU密集型进程统计 ===" >> "$OUTPUT_FILE"
echo "时间戳                PID    %CPU    TIME    COMMAND" >> "$OUTPUT_FILE"
echo "------------------------------------------------" >> "$OUTPUT_FILE"
current_timestamp=""
last_timestamp=""
while read -r line; do
    if [[ "$line" == *"PROCESSES"* ]]; then
        current_timestamp=$(echo "$line" | cut -d' ' -f1,2)
        
        # 如果不是第一次遇到时间戳，添加分割线
        if [[ -n "$last_timestamp" && "$current_timestamp" != "$last_timestamp" ]]; then
            echo "------------------------------------------------" >> "$OUTPUT_FILE"
            echo "== 采样时间: $current_timestamp ==" >> "$OUTPUT_FILE"
            echo "------------------------------------------------" >> "$OUTPUT_FILE"
        elif [[ -z "$last_timestamp" ]]; then
            # 第一次采样时添加时间标识
            echo "== 采样时间: $current_timestamp ==" >> "$OUTPUT_FILE"
            echo "------------------------------------------------" >> "$OUTPUT_FILE"
        fi
        
        last_timestamp="$current_timestamp"
    elif [[ -n "$current_timestamp" ]]; then
        pid=$(echo "$line" | awk '{print $1}')
        cpu=$(echo "$line" | awk '{print $2}')
        time=$(echo "$line" | awk '{print $3}')
        cmd=$(echo "$line" | awk '{print $4}')
        awk -v ts="$current_timestamp" -v p="$pid" -v c="$cpu" -v t="$time" -v cmd="$cmd" \
            'BEGIN {printf "%-20s %6s %7.2f%% %8s %s\n", ts, p, c, t, cmd}' >> "$OUTPUT_FILE"
    fi
done < "$temp_processes"

# 计算平均值
echo -e "\n=== 统计摘要 ===" >> "$OUTPUT_FILE"
echo "------------------------------------------------" >> "$OUTPUT_FILE"

# CPU使用率平均值
cpu_avg=$(awk '/CPU_USAGE/ {sum+=$4; count++} END {print (count>0) ? sum/count : 0}' "$temp_cpu_usage")
cpu_user_avg=$(awk '/CPU_USAGE/ {sum+=$5; count++} END {print (count>0) ? sum/count : 0}' "$temp_cpu_usage")
cpu_system_avg=$(awk '/CPU_USAGE/ {sum+=$6; count++} END {print (count>0) ? sum/count : 0}' "$temp_cpu_usage")
cpu_nice_avg=$(awk '/CPU_USAGE/ {sum+=$7; count++} END {print (count>0) ? sum/count : 0}' "$temp_cpu_usage")
cpu_idle_avg=$(awk '/CPU_USAGE/ {sum+=$8; count++} END {print (count>0) ? sum/count : 0}' "$temp_cpu_usage")
cpu_iowait_avg=$(awk '/CPU_USAGE/ {sum+=$9; count++} END {print (count>0) ? sum/count : 0}' "$temp_cpu_usage")
cpu_hardirq_avg=$(awk '/CPU_USAGE/ {sum+=$10; count++} END {print (count>0) ? sum/count : 0}' "$temp_cpu_usage")
cpu_softirq_avg=$(awk '/CPU_USAGE/ {sum+=$11; count++} END {print (count>0) ? sum/count : 0}' "$temp_cpu_usage")
cpu_steal_avg=$(awk '/CPU_USAGE/ {sum+=$12; count++} END {print (count>0) ? sum/count : 0}' "$temp_cpu_usage")

echo "CPU使用率平均值: ${cpu_avg}% (用户: ${cpu_user_avg}%, 系统: ${cpu_system_avg}%, 优先级: ${cpu_nice_avg}%, 空闲: ${cpu_idle_avg}%, IO等待: ${cpu_iowait_avg}%, 硬中断: ${cpu_hardirq_avg}%, 软中断: ${cpu_softirq_avg}%, 窃取: ${cpu_steal_avg}%)" >> "$OUTPUT_FILE"

# 平均负载最大值
load1_max=$(awk '/LOAD/ {if($4>max) max=$4} END {print max+0}' "$temp_load")
load5_max=$(awk '/LOAD/ {if($5>max) max=$5} END {print max+0}' "$temp_load")
load15_max=$(awk '/LOAD/ {if($6>max) max=$6} END {print max+0}' "$temp_load")
echo "最大平均负载: 1分钟=${load1_max}, 5分钟=${load5_max}, 15分钟=${load15_max}" >> "$OUTPUT_FILE"

# 上下文切换和中断的平均值
context_avg=$(awk '/CONTEXT/ {sum+=$4; count++} END {print (count>0) ? sum/count : 0}' "$temp_context")
voluntary_avg=$(awk '/CONTEXT/ {sum+=$5; count++} END {print (count>0) ? sum/count : 0}' "$temp_context")
nonvoluntary_avg=$(awk '/CONTEXT/ {sum+=$6; count++} END {print (count>0) ? sum/count : 0}' "$temp_context")
echo "平均上下文切换次数: ${context_avg} (主动: ${voluntary_avg}, 被动: ${nonvoluntary_avg})" >> "$OUTPUT_FILE"

hard_interrupts_avg=$(awk '/INTERRUPTS/ {sum+=$4; count++} END {print (count>0) ? sum/count : 0}' "$temp_interrupts")
soft_interrupts_avg=$(awk '/INTERRUPTS/ {sum+=$5; count++} END {print (count>0) ? sum/count : 0}' "$temp_interrupts")
echo "平均中断次数: 硬中断=${hard_interrupts_avg}, 软中断=${soft_interrupts_avg}" >> "$OUTPUT_FILE"

echo -e "\n结束时间: $(date)" >> "$OUTPUT_FILE"
echo "----------------------------------------" >> "$OUTPUT_FILE"

# 正常完成，调用cleanup但不退出
cleanup 